home *** CD-ROM | disk | FTP | other *** search
/ MacHack 2000 / MacHack 2000.toast / pc / The Hacks / Close Window Thing / Close Window Thing.c < prev    next >
C/C++ Source or Header  |  2000-06-23  |  24KB  |  647 lines

  1. #include <Resources.h>
  2. #include <Icons.h>
  3. #include <OSUtils.h>
  4. #include <Sound.h>
  5. #include <Quickdraw.h>
  6. #include <QDOffscreen.h>
  7.  
  8. typedef struct
  9. {
  10.     short    effectType;
  11.     short    speed;
  12. } Preferences;
  13.  
  14. #define kMinimumSystemVersion    0x00000700
  15.  
  16. enum
  17. {
  18.     uppTrackGoAwayProcInfo = kPascalStackBased
  19.         | RESULT_SIZE( SIZE_CODE( sizeof( Boolean ) ) )
  20.         | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(WindowPtr)))
  21.         | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(Point)))
  22. };
  23.  
  24. enum
  25. {
  26.     uppMenuSelectProcInfo = kPascalStackBased
  27.         | RESULT_SIZE( SIZE_CODE( sizeof( long ) ) )
  28.         | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(Point)))
  29. };
  30.  
  31. enum
  32. {
  33.     uppGetNextEventProcInfo = kPascalStackBased
  34.         | RESULT_SIZE( SIZE_CODE( sizeof( Boolean ) ) )
  35.         | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(short)))
  36.         | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(EventRecord *)))
  37. };
  38.  
  39. pascal Boolean NewTrackGoAway( WindowPtr theWindow, Point thePoint );
  40. pascal long NewMenuSelect( Point startPt );
  41. pascal Boolean NewGetNextEvent( short eventMask, EventRecord *theEvent );
  42. Boolean IsFinderFrontProcess( void );
  43. void IsCloseWindow( long theChoice );
  44. void DoLenCloseWindowThing( WindowPtr theWindow );
  45. void DoJoshCloseWindowThing( WindowPtr theWindow );
  46. void LoadPrefs( Preferences *prefs );
  47. void NewPrefs( Preferences *prefs, FSSpec spec, short *prefsFRefNum );
  48.  
  49. UniversalProcPtr    gOldTrackGoAway = nil, gNewTrackGoAway;
  50. UniversalProcPtr    gOldMenuSelect = nil, gNewMenuSelect;
  51. UniversalProcPtr    gOldGetNextEvent = nil, gNewGetNextEvent;
  52. QDGlobals            qd;
  53. Preferences            **prefsHan, prefs;
  54.  
  55. void main(void)
  56. {
  57.     OSErr    err = noErr;
  58.     THz        oldZone;
  59.     
  60.     // Save the old zone and set the current zone to the system zone
  61.     oldZone = GetZone();
  62.     SetZone( SystemZone() );
  63.     
  64.     // Preserve our code in memory
  65.     DetachResource(GetResource('INIT', 0));
  66.     
  67.     // Get the address of the TrackGoAway trap
  68.     gOldTrackGoAway = GetToolTrapAddress( _TrackGoAway );
  69.     // Create a routine descriptor for our new TrackGoAway function
  70.     gNewTrackGoAway = NewRoutineDescriptor( (ProcPtr) &NewTrackGoAway, uppTrackGoAwayProcInfo,kPowerPCISA);
  71.     // Patch our function into the trap table
  72.     SetToolTrapAddress( gNewTrackGoAway, _TrackGoAway );
  73.     
  74.     // Get the address of the MenuSelect trap
  75.     gOldMenuSelect = GetToolTrapAddress( _MenuSelect );
  76.     // Create a routine descriptor for our new MenuSelect function
  77.     gNewMenuSelect = NewRoutineDescriptor( (ProcPtr)&NewMenuSelect, uppMenuSelectProcInfo,kPowerPCISA);
  78.     // Patch our function into the trap table
  79.     SetToolTrapAddress( gNewMenuSelect, _MenuSelect );
  80.     
  81.     // Get the address of the GetNextEvent trap
  82.     gOldGetNextEvent = GetToolTrapAddress( _GetNextEvent );
  83.     // Create a routine descriptor for our new GetNextEvent function
  84.     gNewGetNextEvent = NewRoutineDescriptor( (ProcPtr)&NewGetNextEvent, uppGetNextEventProcInfo, kPowerPCISA );
  85.     // Patch our function into the trap table
  86.     SetToolTrapAddress( gNewGetNextEvent, _GetNextEvent );
  87.     
  88.     LoadPrefs( &prefs );
  89.     
  90.     // Restore the old zone
  91.     SetZone(oldZone);
  92. }
  93.  
  94. pascal Boolean NewTrackGoAway( WindowPtr theWindow, Point thePoint )
  95. {
  96.     Boolean        result;
  97.     
  98.     // Head Patch
  99.     result = CallUniversalProc( gOldTrackGoAway, uppTrackGoAwayProcInfo, theWindow, thePoint );
  100.     
  101.     // Only run if the Finder is the front process and user wants to close the window
  102.     if ( IsFinderFrontProcess() && result )
  103.     {
  104.         // Do our pre-closing show
  105.         LoadPrefs( &prefs );
  106.         
  107.         if ( prefs.effectType == 1 )
  108.             DoLenCloseWindowThing( theWindow );
  109.         else if ( prefs.effectType == 2 )
  110.             DoJoshCloseWindowThing( theWindow );
  111.     }
  112.     
  113.     return result;
  114. }
  115.  
  116. pascal long NewMenuSelect( Point startPt )
  117. {
  118.     long    result;
  119.     
  120.     // Head Patch
  121.     result = CallUniversalProc( gOldMenuSelect, uppMenuSelectProcInfo, startPt );
  122.     
  123.     // Only run if the Finder is the front process
  124.     if ( IsFinderFrontProcess() )
  125.     {
  126.         // Dis the user choose "Close Window"?
  127.         IsCloseWindow( result );
  128.     }
  129.     
  130.     return result;
  131. }
  132.  
  133. pascal Boolean NewGetNextEvent( short eventMask, EventRecord *theEvent )
  134. {
  135.     long    result;
  136.     
  137.     // Head Patch
  138.     result = CallUniversalProc( gOldGetNextEvent, uppGetNextEventProcInfo, eventMask, theEvent );
  139.     
  140.     // Only run if the Finder is the front proccess
  141.     if ( IsFinderFrontProcess() )
  142.     {
  143.         // Did the user choose "Close Window?"
  144.         
  145.         if ( theEvent->what == keyDown )
  146.         {
  147.             short    theChar;
  148.             
  149.             theChar = theEvent->message & charCodeMask;
  150.             
  151.             if ( ( theEvent->modifiers & cmdKey ) != 0 )
  152.             {
  153.                 if ( theEvent->what != autoKey )
  154.                 {
  155.                     if ( theChar == 'w' )
  156.                     {
  157.                         LoadPrefs( &prefs );
  158.                         
  159.                         if ( prefs.effectType == 1 )
  160.                             DoLenCloseWindowThing( LMGetWindowList() );
  161.                         else if ( prefs.effectType == 2 )
  162.                             DoJoshCloseWindowThing( LMGetWindowList() );
  163.                     }
  164.                 }
  165.             }
  166.         }
  167.     }
  168.     
  169.     return result;
  170. }
  171.  
  172. Boolean IsFinderFrontProcess( void )
  173. {
  174.     ProcessSerialNumber    finderPSN, curPSN;
  175.     ProcessInfoRec        theProc;
  176.     Boolean                sameProcess;
  177.     
  178.     finderPSN.highLongOfPSN = 0;
  179.     finderPSN.lowLongOfPSN = kNoProcess;
  180.     
  181.     theProc.processInfoLength = sizeof(ProcessInfoRec);
  182.     theProc.processName = nil;
  183.     theProc.processAppSpec = nil;
  184.     theProc.processLocation = nil;
  185.     
  186.     // Check every process until we locate the Finder
  187.     while (true) 
  188.     {
  189.         GetNextProcess( &finderPSN );
  190.         GetProcessInformation( &finderPSN, &theProc );
  191.         if ( ( theProc.processType == 'FNDR' ) && ( theProc.processSignature == 'MACS' ) )
  192.             break;
  193.     }
  194.     
  195.     // Get the Process Serial Number of the front process
  196.     GetFrontProcess( &curPSN );
  197.     // Compare it to the Finder's process serial number
  198.     SameProcess( &finderPSN, &curPSN, &sameProcess );
  199.     
  200.     return sameProcess;
  201. }
  202.  
  203. // Does the user want to close the window?
  204. void IsCloseWindow( long theChoice )
  205. {
  206.     MenuHandle    menuHandle;
  207.     Str255        theString;
  208.     short        theMenu, theMenuItem;
  209.     
  210.     theMenu = HiWord( theChoice );
  211.     theMenuItem = LoWord( theChoice );
  212.     
  213.     // Get a handle to the chosen menu
  214.     menuHandle = GetMenuHandle( theMenu );
  215.     // Get the name of the item chosen
  216.     GetMenuItemText( menuHandle, theMenuItem, theString );
  217.     // Is the name of the item chosen "Close Window" so we can do our pre-closing show?
  218.     if ( EqualString( theString, "\pClose Window", false, false ) )
  219.     {
  220.         LoadPrefs( &prefs );
  221.         
  222.         if ( prefs.effectType == 1 )
  223.             DoLenCloseWindowThing( LMGetWindowList() );
  224.         else if ( prefs.effectType == 2 )
  225.             DoJoshCloseWindowThing( LMGetWindowList() );
  226.     }
  227. }
  228.  
  229. void DoLenCloseWindowThing( WindowPtr theWindow )
  230. {
  231.     WindowPtr    savePort;
  232.     GrafPtr        theScreen;
  233.     GDHandle    saveDevice;
  234.     GWorldPtr    windowWorld, backgroundWorld, scrapWorld, 
  235.                 theOffScreen0, theOffScreen1, theOffScreen2, theOffScreen3, 
  236.                 theOffScreen4, theOffScreen5, theOffScreen6, theOffScreen7;
  237.     Rect        screenRect, globalWindow, localWindow, centerWindow, globalScrap, localScrap;
  238.     Rect        windowRect00, windowRect01, windowRect02, windowRect03,
  239.                 windowRect10, windowRect11, windowRect12, windowRect13,
  240.                 locWindowRect00, locWindowRect01, locWindowRect02, locWindowRect03, 
  241.                 locWindowRect10, locWindowRect11, locWindowRect12, locWindowRect13,
  242.                 locWindowSRect00, locWindowSRect01, locWindowSRect02, locWindowSRect03, 
  243.                 locWindowSRect10, locWindowSRect11, locWindowSRect12, locWindowSRect13;
  244.     Str255        name;
  245.                 
  246.     GetWTitle( theWindow, name );
  247.     if ( EqualString( name, "\pDesktop", false, false ) )
  248.         return;
  249.     
  250.     // Get the Color Window Manager's port (To draw to the screen)
  251.     GetCWMgrPort( &(CGrafPort *)theScreen );
  252.     // Save the current GWorld
  253.     GetGWorld( &(CGrafPtr)savePort, &saveDevice );
  254.     // Set the QuickDraw port to the window to play with
  255.     SetPort( theWindow );
  256.     
  257.     // Calculate our rectangles
  258.     screenRect = theScreen->portRect;
  259.     OffsetRect( &screenRect, -screenRect.left, -screenRect.top );
  260.     localWindow = theWindow->portRect;
  261.     OffsetRect( &localWindow, -localWindow.left, -localWindow.top );
  262.     globalWindow = localWindow;
  263.     localWindow.bottom += 27;
  264.     localWindow.right += 11;
  265.     LocalToGlobal( (Point *)&globalWindow );
  266.     LocalToGlobal( (Point *)&globalWindow.bottom );
  267.     globalWindow.top -= 22;
  268.     globalWindow.left -= 6;
  269.     globalWindow.bottom += 7;
  270.     globalWindow.right += 7;
  271.     
  272.     localScrap = localWindow;
  273.     localScrap.right += 10;
  274.     centerWindow = localScrap;
  275.     centerWindow.right -= 10;
  276.     centerWindow.left += 10;
  277.     
  278.     globalScrap = globalWindow;
  279.     globalScrap.left -= 10;
  280.     globalScrap.right += 10;
  281.     
  282.     // Create our three offscreen graphics worlds
  283.     NewGWorld( &windowWorld, 0, &localWindow, 0, 0, useTempMem );
  284.     NewGWorld( &backgroundWorld, 0, &screenRect, 0, 0, useTempMem );
  285.     NewGWorld( &scrapWorld, 0, &localScrap, 0, 0, useTempMem );
  286.     
  287.     // Copy the window we're playing with into its offscreen world
  288.     SetGWorld( windowWorld, NULL );
  289.     CopyBits( &theScreen->portBits, &((GrafPtr)windowWorld)->portBits, &globalWindow, &localWindow, srcCopy, NULL );
  290.     
  291.     
  292.     // Hide our window and take a short break
  293.     HideWindow( theWindow );
  294.     GetNextEvent( nil, nil );
  295.     // Copy the screen to the background world again
  296.     SetGWorld( backgroundWorld, NULL );
  297.     CopyBits( &theScreen->portBits, &((GrafPtr)backgroundWorld)->portBits, &screenRect, &screenRect, srcCopy, NULL );
  298.     
  299.     // Set the Graphics World to an offscreen world
  300.     SetGWorld( scrapWorld, NULL );
  301.     
  302.     //Works
  303.     windowRect00.top = globalWindow.top;
  304.     windowRect00.left = (globalWindow.left);
  305.     windowRect00.bottom = ((localWindow.bottom / 2) + globalWindow.top);
  306.     windowRect00.right = ((localWindow.right / 4) + globalWindow.left);
  307.     
  308.     //Works
  309.     windowRect01.top = globalWindow.top;
  310.     windowRect01.left = windowRect00.right;
  311.     windowRect01.bottom = ((localWindow.bottom / 2) + globalWindow.top);
  312.     windowRect01.right = ((localWindow.right / 2) + globalWindow.left);
  313.     
  314.     //Works
  315.     windowRect02.top = globalWindow.top;
  316.     windowRect02.left = windowRect01.right;
  317.     windowRect02.bottom = ((localWindow.bottom / 2) + globalWindow.top);
  318.     windowRect02.right = (((localWindow.right / 4) * 3) + globalWindow.left);
  319.     
  320.     //Works
  321.     windowRect03.top = globalWindow.top;
  322.     windowRect03.left = windowRect02.right;
  323.     windowRect03.bottom = ((localWindow.bottom / 2) + globalWindow.top);
  324.     windowRect03.right = globalWindow.right;
  325.     
  326.     //Works
  327.     windowRect10.top = ((localWindow.bottom / 2) + globalWindow.top);
  328.     windowRect10.left = globalWindow.left;
  329.     windowRect10.bottom = globalWindow.bottom - 1;
  330.     windowRect10.right = ((localWindow.right / 4) + globalWindow.left);
  331.     
  332.     //Works
  333.     windowRect11.top = ((localWindow.bottom / 2) + globalWindow.top);
  334.     windowRect11.left = windowRect10.right;
  335.     windowRect11.bottom = globalWindow.bottom;
  336.     windowRect11.right = ((localWindow.right / 2) + globalWindow.left);
  337.     
  338.     //Works
  339.     windowRect12.top = ((localWindow.bottom / 2) + globalWindow.top);
  340.     windowRect12.left = windowRect11.right;
  341.     windowRect12.bottom = globalWindow.bottom;
  342.     windowRect12.right = (((localWindow.right / 4) * 3) + globalWindow.left);
  343.     
  344.     //Works
  345.     windowRect13.top = (( localWindow.bottom / 2 ) + globalWindow.top);
  346.     windowRect13.left = windowRect12.right;
  347.     windowRect13.bottom = globalWindow.bottom - 1;
  348.     windowRect13.right = globalWindow.right;
  349.     
  350.     
  351.     NewGWorld( &theOffScreen0, 0, &windowRect00, 0, 0, useTempMem );
  352.     NewGWorld( &theOffScreen1, 0, &windowRect01, 0, 0, useTempMem );
  353.     NewGWorld( &theOffScreen2, 0, &windowRect02, 0, 0, useTempMem );
  354.     NewGWorld( &theOffScreen3, 0, &windowRect03, 0, 0, useTempMem );
  355.     NewGWorld( &theOffScreen4, 0, &windowRect10, 0, 0, useTempMem );
  356.     NewGWorld( &theOffScreen5, 0, &windowRect11, 0, 0, useTempMem );
  357.     NewGWorld( &theOffScreen6, 0, &windowRect12, 0, 0, useTempMem );
  358.     NewGWorld( &theOffScreen7, 0, &windowRect13, 0, 0, useTempMem );
  359.     
  360.     locWindowRect00 = theOffScreen0->portRect;
  361.     locWindowSRect00 = theOffScreen0->portRect;
  362.     //theOffScreen0->portRect.bottom     += 2;
  363.     //theOffScreen0->portRect.right      += 3;
  364.     OffsetRect( &locWindowRect00, -3, -2 );
  365.     
  366.     locWindowRect01 = theOffScreen1->portRect;
  367.     locWindowSRect01 = theOffScreen1->portRect;
  368.     //theOffScreen1->portRect.bottom     += 3;
  369.     //theOffScreen1->portRect.right      += 2;
  370.     OffsetRect( &locWindowRect01, -2, -3 );
  371.     
  372.     locWindowRect02 = theOffScreen2->portRect;
  373.     locWindowSRect02 = theOffScreen2->portRect;
  374.     //theOffScreen2->portRect.bottom     += 3;
  375.     //theOffScreen2->portRect.left       -= 2;
  376.     OffsetRect( &locWindowRect02, 2, -3 );
  377.     
  378.     locWindowRect03 = theOffScreen3->portRect;
  379.     locWindowSRect03 = theOffScreen3->portRect;
  380.     //theOffScreen3->portRect.bottom     += 2;
  381.     //theOffScreen3->portRect.left       -= 3;
  382.     OffsetRect( &locWindowRect03, 3, -2 );
  383.     
  384.     locWindowRect10 = theOffScreen4->portRect;
  385.     locWindowSRect10 = theOffScreen4->portRect;
  386.     //theOffScreen4->portRect.top        -= 2;
  387.     //theOffScreen4->portRect.right      += 3;
  388.     OffsetRect( &locWindowRect10, -3, 2 );
  389.     
  390.     locWindowRect11 = theOffScreen5->portRect;
  391.     locWindowSRect11 = theOffScreen5->portRect;
  392.     //theOffScreen5->portRect.top        -= 3;
  393.     //theOffScreen5->portRect.right    += 2;
  394.     OffsetRect( &locWindowRect11, -2, 3 );
  395.     
  396.     locWindowRect12 = theOffScreen6->portRect;
  397.     locWindowSRect12 = theOffScreen6->portRect;
  398.     //theOffScreen6->portRect.top     -= 3;
  399.     //theOffScreen6->portRect.left    -= 2;
  400.     OffsetRect( &locWindowRect12, 2, 3 );
  401.     
  402.     locWindowRect13 = theOffScreen7->portRect;
  403.     locWindowSRect13 = theOffScreen7->portRect;
  404.     //theOffScreen7->portRect.top        -= 2;
  405.     //theOffScreen7->portRect.left    -= 3;
  406.     OffsetRect( &locWindowRect13, 3, 2 );
  407.     
  408.     OffsetRect( &locWindowSRect01, locWindowSRect00.right, NULL );
  409.     OffsetRect( &locWindowSRect02, locWindowSRect01.right, NULL );
  410.     OffsetRect( &locWindowSRect03, locWindowSRect02.right, NULL );
  411.     OffsetRect( &locWindowSRect10, NULL, locWindowSRect00.bottom );
  412.     OffsetRect( &locWindowSRect11, locWindowSRect10.right, locWindowSRect01.bottom );
  413.     OffsetRect( &locWindowSRect12, locWindowSRect11.right, locWindowSRect02.bottom );
  414.     OffsetRect( &locWindowSRect13, locWindowSRect12.right, locWindowSRect03.bottom );
  415.     
  416.     windowRect00.bottom += 2;
  417.     windowRect00.right    += 3;
  418.     
  419.     windowRect01.bottom += 3;
  420.     windowRect01.right    += 2;
  421.     
  422.     windowRect02.bottom    += 3;
  423.     windowRect02.left    -= 2;
  424.     
  425.     windowRect03.bottom += 2;
  426.     windowRect03.left    -= 3;
  427.     
  428.     windowRect10.top    -= 2;
  429.     windowRect10.right    += 3;
  430.     
  431.     windowRect11.top    -= 3;
  432.     windowRect11.right    += 2;
  433.     
  434.     windowRect12.top    -= 3;
  435.     windowRect12.left    -= 2;
  436.  
  437.     windowRect13.top     -= 2;
  438.     windowRect13.left     -= 3;
  439.     
  440.     UpdateGWorld(&theOffScreen0, 0, &windowRect00, 0, 0, useTempMem);
  441.     UpdateGWorld(&theOffScreen1, 0, &windowRect01, 0, 0, useTempMem);
  442.     UpdateGWorld(&theOffScreen2, 0, &windowRect02, 0, 0, useTempMem);
  443.     UpdateGWorld(&theOffScreen3, 0, &windowRect03, 0, 0, useTempMem);
  444.     UpdateGWorld(&theOffScreen4, 0, &windowRect10, 0, 0, useTempMem);
  445.     UpdateGWorld(&theOffScreen5, 0, &windowRect11, 0, 0, useTempMem);
  446.     UpdateGWorld(&theOffScreen6, 0, &windowRect12, 0, 0, useTempMem);
  447.     UpdateGWorld(&theOffScreen7, 0, &windowRect13, 0, 0, useTempMem);
  448.  
  449.  
  450.     do    {
  451.         // Copy the background into theOffScreen scrap world
  452.         CopyBits( &((GrafPtr)backgroundWorld)->portBits, &((GrafPtr)theOffScreen0)->portBits, &windowRect00, &theOffScreen0->portRect, srcCopy, NULL );
  453.         CopyBits( &((GrafPtr)backgroundWorld)->portBits, &((GrafPtr)theOffScreen1)->portBits, &windowRect01, &theOffScreen1->portRect, srcCopy, NULL );
  454.         CopyBits( &((GrafPtr)backgroundWorld)->portBits, &((GrafPtr)theOffScreen2)->portBits, &windowRect02, &theOffScreen2->portRect, srcCopy, NULL );
  455.         CopyBits( &((GrafPtr)backgroundWorld)->portBits, &((GrafPtr)theOffScreen3)->portBits, &windowRect03, &theOffScreen3->portRect, srcCopy, NULL );
  456.         CopyBits( &((GrafPtr)backgroundWorld)->portBits, &((GrafPtr)theOffScreen4)->portBits, &windowRect10, &theOffScreen4->portRect, srcCopy, NULL );
  457.         CopyBits( &((GrafPtr)backgroundWorld)->portBits, &((GrafPtr)theOffScreen5)->portBits, &windowRect11, &theOffScreen5->portRect, srcCopy, NULL );
  458.         CopyBits( &((GrafPtr)backgroundWorld)->portBits, &((GrafPtr)theOffScreen6)->portBits, &windowRect12, &theOffScreen6->portRect, srcCopy, NULL );
  459.         CopyBits( &((GrafPtr)backgroundWorld)->portBits, &((GrafPtr)theOffScreen7)->portBits, &windowRect13, &theOffScreen7->portRect, srcCopy, NULL );
  460.  
  461.         // Copy the window into the scrap world
  462.         CopyBits( &((GrafPtr)windowWorld)->portBits, &((GrafPtr)theOffScreen0)->portBits, &locWindowSRect00, &locWindowRect00, srcCopy, NULL );
  463.         CopyBits( &((GrafPtr)windowWorld)->portBits, &((GrafPtr)theOffScreen1)->portBits, &locWindowSRect01, &locWindowRect01, srcCopy, NULL );
  464.         CopyBits( &((GrafPtr)windowWorld)->portBits, &((GrafPtr)theOffScreen2)->portBits, &locWindowSRect02, &locWindowRect02, srcCopy, NULL );
  465.         CopyBits( &((GrafPtr)windowWorld)->portBits, &((GrafPtr)theOffScreen3)->portBits, &locWindowSRect03, &locWindowRect03, srcCopy, NULL );
  466.         CopyBits( &((GrafPtr)windowWorld)->portBits, &((GrafPtr)theOffScreen4)->portBits, &locWindowSRect10, &locWindowRect10, srcCopy, NULL );
  467.         CopyBits( &((GrafPtr)windowWorld)->portBits, &((GrafPtr)theOffScreen5)->portBits, &locWindowSRect11, &locWindowRect11, srcCopy, NULL );
  468.         CopyBits( &((GrafPtr)windowWorld)->portBits, &((GrafPtr)theOffScreen6)->portBits, &locWindowSRect12, &locWindowRect12, srcCopy, NULL );
  469.         CopyBits( &((GrafPtr)windowWorld)->portBits, &((GrafPtr)theOffScreen7)->portBits, &locWindowSRect13, &locWindowRect13, srcCopy, NULL );
  470.  
  471.         // Copy the contents of the scrap world to the screen
  472.         CopyBits( &((GrafPtr)theOffScreen0)->portBits, &((GrafPtr)theScreen)->portBits, &theOffScreen0->portRect, &windowRect00, srcCopy, NULL );
  473.         CopyBits( &((GrafPtr)theOffScreen1)->portBits, &((GrafPtr)theScreen)->portBits, &theOffScreen1->portRect, &windowRect01, srcCopy, NULL );
  474.         CopyBits( &((GrafPtr)theOffScreen2)->portBits, &((GrafPtr)theScreen)->portBits, &theOffScreen2->portRect, &windowRect02, srcCopy, NULL );
  475.         CopyBits( &((GrafPtr)theOffScreen3)->portBits, &((GrafPtr)theScreen)->portBits, &theOffScreen3->portRect, &windowRect03, srcCopy, NULL );
  476.         CopyBits( &((GrafPtr)theOffScreen4)->portBits, &((GrafPtr)theScreen)->portBits, &theOffScreen4->portRect, &windowRect10, srcCopy, NULL );
  477.         CopyBits( &((GrafPtr)theOffScreen5)->portBits, &((GrafPtr)theScreen)->portBits, &theOffScreen5->portRect, &windowRect11, srcCopy, NULL );
  478.         CopyBits( &((GrafPtr)theOffScreen6)->portBits, &((GrafPtr)theScreen)->portBits, &theOffScreen6->portRect, &windowRect12, srcCopy, NULL );
  479.         CopyBits( &((GrafPtr)theOffScreen7)->portBits, &((GrafPtr)theScreen)->portBits, &theOffScreen7->portRect, &windowRect13, srcCopy, NULL );
  480.  
  481.         OffsetRect( &windowRect00, -3, -2);
  482.         OffsetRect( &windowRect01, -2, -3);
  483.         OffsetRect( &windowRect02,  2, -3);
  484.         OffsetRect( &windowRect03,  3, -2);
  485.         OffsetRect( &windowRect10, -3,  2);
  486.         OffsetRect( &windowRect11, -2,  3);
  487.         OffsetRect( &windowRect12,  2,  3);
  488.         OffsetRect( &windowRect13,  3,  2);
  489.         }    while (  (windowRect00.right > 0) || (windowRect01.bottom > 0) || (windowRect02.bottom > 0) || (windowRect03.left < theScreen->portRect.right) || 
  490.                      (windowRect10.right > 0) || (windowRect11.top < theScreen->portRect.bottom) || (windowRect12.top < theScreen->portRect.bottom) || 
  491.                       (windowRect13.left < theScreen->portRect.right) );
  492.     
  493.     // Clean up by setting the screen to its origional state
  494.     CopyBits( &((GrafPtr)backgroundWorld)->portBits, &theScreen->portBits, &screenRect, &screenRect, srcCopy, NULL );
  495.     
  496.     // Kill our graphics worlds
  497.     DisposeGWorld( windowWorld );
  498.     DisposeGWorld( backgroundWorld );
  499.     DisposeGWorld( scrapWorld );
  500.     DisposeGWorld( theOffScreen0 );
  501.     DisposeGWorld( theOffScreen1 );
  502.     DisposeGWorld( theOffScreen2 );
  503.     DisposeGWorld( theOffScreen3 );
  504.     DisposeGWorld( theOffScreen4 );
  505.     DisposeGWorld( theOffScreen5 );
  506.     DisposeGWorld( theOffScreen6 );
  507.     DisposeGWorld( theOffScreen7 );            
  508.     
  509.     // Reset the previous state of QuickDraw
  510.     SetGWorld( (CGrafPtr)savePort, saveDevice );
  511. }
  512.  
  513. void DoJoshCloseWindowThing( WindowPtr theWindow )
  514. {
  515.     WindowPtr    savePort;
  516.     GrafPtr        theScreen;
  517.     GDHandle    saveDevice;
  518.     GWorldPtr    windowWorld, backgroundWorld, scrapWorld;
  519.     Rect        screenRect, globalWindow, localWindow, centerWindow, localScrap, globalScrap;
  520.     Str255        name;
  521.     
  522.     GetWTitle( theWindow, name );
  523.     if ( EqualString( name, "\pDesktop", false, false ) )
  524.         return;
  525.     
  526.     // Get the Color Window Manager's port (To draw to the screen)
  527.     GetCWMgrPort( &(CGrafPort *)theScreen );
  528.     // Save the current GWorld
  529.     GetGWorld( &(CGrafPtr)savePort, &saveDevice );
  530.     // Set the QuickDraw port to the window to play with
  531.     SetPort( theWindow );
  532.     
  533.     // Calculate our rectangles
  534.     screenRect = theScreen->portRect;
  535.     OffsetRect( &screenRect, -screenRect.left, -screenRect.top );
  536.     localWindow = theWindow->portRect;
  537.     OffsetRect( &localWindow, -localWindow.left, -localWindow.top );
  538.     globalWindow = localWindow;
  539.     localWindow.bottom += 27;
  540.     localWindow.right += 11;
  541.     LocalToGlobal( (Point *)&globalWindow );
  542.     LocalToGlobal( (Point *)&globalWindow.bottom );
  543.     globalWindow.top -= 22;
  544.     globalWindow.left -= 6;
  545.     globalWindow.bottom += 7;
  546.     globalWindow.right += 7;
  547.     
  548.     localScrap = localWindow;
  549.     localScrap.right += 10;
  550.     centerWindow = localScrap;
  551.     centerWindow.right -= 5 * prefs.speed;
  552.     centerWindow.left += 5 * prefs.speed;
  553.     
  554.     globalScrap = globalWindow;
  555.     globalScrap.left -= 5 * prefs.speed;
  556.     globalScrap.right += 5 * prefs.speed;
  557.     
  558.     // Create our three offscreen graphics worlds
  559.     NewGWorld( &windowWorld, 0, &localWindow, 0, 0, useTempMem );
  560.     NewGWorld( &backgroundWorld, 0, &screenRect, 0, 0, useTempMem );
  561.     NewGWorld( &scrapWorld, 0, &localScrap, 0, 0, useTempMem );
  562.     
  563.     // Copy the window we're playing with into its offscreen world
  564.     SetGWorld( windowWorld, NULL );
  565.     CopyBits( &theScreen->portBits, &((GrafPtr)windowWorld)->portBits, &globalWindow, &localWindow, srcCopy, NULL );
  566.     // Hide our window and take a short break
  567.     HideWindow( theWindow );
  568.     GetNextEvent( nil, nil );
  569.     // Copy the screen to the background world
  570.     SetGWorld( backgroundWorld, NULL );
  571.     CopyBits( &theScreen->portBits, &((GrafPtr)backgroundWorld)->portBits, &screenRect, &screenRect, srcCopy, NULL );
  572.     
  573.     // Set the Graphics World to an offscreen world
  574.     SetGWorld( scrapWorld, NULL );
  575.     
  576.     do
  577.     {
  578.         // Copy the background into the scrap world
  579.         CopyBits( &((GrafPtr)backgroundWorld)->portBits, &((GrafPtr)scrapWorld)->portBits, &globalScrap, &localScrap, srcCopy, NULL );
  580.         // Copy the window into the scrap world
  581.         CopyBits( &((GrafPtr)windowWorld)->portBits, &((GrafPtr)scrapWorld)->portBits, &localWindow, ¢erWindow, srcCopy, NULL );
  582.         // Copy the contents of the scrap world to the screen
  583.         CopyBits( &((GrafPtr)scrapWorld)->portBits, &theScreen->portBits, &localScrap, &globalScrap, srcCopy, NULL );
  584.         
  585.         // Update the rectangle for the next time through
  586.         globalScrap.left -= 5 * prefs.speed;
  587.         globalScrap.right -= 5 * prefs.speed;
  588.     }
  589.     while ( globalScrap.right > 0 );
  590.     
  591.     // Clean up by setting the screen to its origional state
  592.     CopyBits( &((GrafPtr)backgroundWorld)->portBits, &theScreen->portBits, &screenRect, &screenRect, srcCopy, NULL );
  593.     
  594.     // Kill our graphics worlds
  595.     DisposeGWorld( windowWorld );
  596.     DisposeGWorld( backgroundWorld );
  597.     DisposeGWorld( scrapWorld );
  598.     
  599.     // Reset the previous state of QuickDraw
  600.     SetGWorld( (CGrafPtr)savePort, saveDevice );
  601. }
  602.  
  603. void LoadPrefs( Preferences *prefs )
  604. {
  605.     OSErr    myErr;
  606.     FSSpec    mySpec;
  607.     short    myVRef, prefsFRefNum;
  608.     long    myDirID;
  609.     
  610.     myErr = FindFolder(0x8000, 'pref', false, &myVRef, &myDirID);
  611.     myErr = FSMakeFSSpec( myVRef, myDirID, "\pClose Window Thing Prefs", &mySpec );
  612.     
  613.     if( myErr == fnfErr )
  614.         NewPrefs( prefs, mySpec, &prefsFRefNum );
  615.     
  616.     prefsFRefNum = FSpOpenResFile( &mySpec,3 );
  617.     
  618.     prefsHan = (Preferences **)GetResource( 'Pref',128 );
  619.     
  620.     prefs->effectType = (**prefsHan).effectType;
  621.     prefs->speed = (**prefsHan).speed;
  622.     
  623.     if ( prefsHan != nil )
  624.         ReleaseResource( (Handle)prefsHan );
  625.     if ( prefsFRefNum )
  626.         FSClose( prefsFRefNum );
  627. }
  628.  
  629. void NewPrefs( Preferences *prefs, FSSpec spec, short *prefsFRefNum )
  630. {
  631.     FSpCreateResFile( &spec, 'PEJ2', 'pref', -1 );
  632.     *prefsFRefNum = FSpOpenResFile( &spec, 3 );
  633.     
  634.     prefs->effectType = 1;
  635.     prefs->speed = 1;
  636.     
  637.     (Handle)prefsHan = NewHandle( sizeof( Preferences ) );
  638.     (**prefsHan).effectType = prefs->effectType;
  639.     (**prefsHan).speed = prefs->speed;
  640.     
  641.     HLock( (Handle)prefsHan );
  642.     AddResource( (Handle)prefsHan, 'Pref', 128, "\pPrefs");
  643.     WriteResource( (Handle)prefsHan );
  644.     HUnlock( (Handle)prefsHan );
  645.     
  646.       UpdateResFile( *prefsFRefNum );
  647. }